package com.zhiche.lisa.bms.service.bill.impl;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.lisa.bms.dao.mapper.bill.BillMapper;
import com.zhiche.lisa.bms.dao.model.bill.*;
import com.zhiche.lisa.bms.dao.model.charge.ChargeOffRule;
import com.zhiche.lisa.bms.dao.model.contract.Contract;
import com.zhiche.lisa.bms.dao.model.contract.ContractFleetDtl;
import com.zhiche.lisa.bms.dao.model.fee.FeePayable;
import com.zhiche.lisa.bms.dao.model.fee.FeeReceivable;
import com.zhiche.lisa.bms.dao.model.pay.PayApplyDtlBill;
import com.zhiche.lisa.bms.dao.model.quote.Quote;
import com.zhiche.lisa.bms.enums.FleetAttributeEnum;
import com.zhiche.lisa.bms.pojo.dto.util.CustBillDTO;
import com.zhiche.lisa.bms.pojo.dto.util.CustBillDetailDTO;
import com.zhiche.lisa.bms.pojo.vo.bill.*;
import com.zhiche.lisa.bms.pojo.vo.fee.FeePayableVO;
import com.zhiche.lisa.bms.service.bill.*;
import com.zhiche.lisa.bms.service.charge.ChargeOffRuleService;
import com.zhiche.lisa.bms.service.contract.ContractFleetDtlService;
import com.zhiche.lisa.bms.service.contract.ContractService;
import com.zhiche.lisa.bms.service.fee.FeePayableService;
import com.zhiche.lisa.bms.service.fee.FeeReceivableService;
import com.zhiche.lisa.bms.service.pay.PayApplyDtlBillService;
import com.zhiche.lisa.bms.service.quote.QuoteService;
import com.zhiche.lisa.bms.service.utils.LspUtil;
import com.zhiche.lisa.bms.service.utils.OtmUtil;
import com.zhiche.lisa.bms.service.utils.common.AccountBindUtil;
import com.zhiche.lisa.bms.service.utils.common.BeanColumnUtil;
import com.zhiche.lisa.bms.service.utils.common.identityCodeUtil.CodeUtil;
import com.zhiche.lisa.core.enums.BillStatusEnum;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.utils.Account.AccountUtil;
import com.zhiche.lisa.core.utils.Account.JwtAccountVO;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 账单 服务实现类
 * </p>
 *
 * @author liuanshun
 * @since 2018-09-06
 */
@Service
public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements BillService {

    private Logger LOGGER = LoggerFactory.getLogger(BillServiceImpl.class);

    /**
     * 应付类型
     */
    private String BILLPAYABLETYPE = "20";
    /**
     * 应收类型
     */
    private String BILLRECEIVABLETYPE = "10";

    @Autowired
    private LspUtil lspUtil;

    @Autowired
    private BillDetailService billDetailService;

    @Autowired
    private FeeReceivableService feeReceivableService;

    @Autowired
    private BillIoDetailService billIoDetailService;

    @Autowired
    private BillIoService billIoService;

    @Autowired
    private FeePayableService feePayableService;

    @Autowired
    private OtmUtil otmUtil;

    @Autowired
    private CodeUtil codeUtil;

    @Autowired
    private ExceptionBillDtlService exceptionBillDtlService;

    @Autowired
    private ExceptionBillService exceptionBillService;

    @Autowired
    private PayApplyDtlBillService payApplyDtlBillService;

    @Autowired
    private ChargeOffRuleService chargeOffRuleService;

    static final String INCOME_BILL = "AR";//应收账单

    static final String PAYMENT_BILL = "AP";//应付账单

    @Autowired
    private ContractService contractService;

    @Autowired
    private ContractFleetDtlService contractFleetDtlService;

    @Autowired
    private QuoteService quoteService;

    /**
     * 绑定状态名称
     *
     * @param bill
     * @return
     */
    private BillVO bindBillStatuName(Bill bill) {
        BillVO billVO = new BillVO();
        //复制基本信息并绑定状态结果和客户确认结果
        BeanUtils.copyProperties(bill, billVO);
        if (Objects.nonNull(bill.getBillStatus())) {
            String billStatu = bill.getBillStatus();
            for (BillStatusEnum billStatus :
                    BillStatusEnum.values()) {
                billStatu = billStatu.replace(billStatus.getCode(), billStatus.getText());
            }
            billVO.setBillStatuName(billStatu);
        }
        if (Objects.nonNull(bill.getIsAffirm())) {
            billVO.setIsAffirmVal(bill.getIsAffirm().toString().equals("1") ? "是" : "否");
        }
        return billVO;
    }

    /**
     * 应收账单分页数据
     *
     * @param inPage
     * @return
     */
    @Override
    public Page<BillVO> selectIncomingPage(Page inPage) {
//         try {
// //            JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
//             //查询账单信息
//             Page<BillVO> billPage = new Page<>();
//             EntityWrapper entityWrapper = bindIncomingContition(inPage.getCondition());
//             List<Bill> billList = baseMapper.selectPage(inPage.setCondition(Maps.newHashMap()), entityWrapper);
//             BeanUtils.copyProperties(inPage, billPage);
//             List<BillVO> billVoList = Lists.newArrayList();
//             //绑定状态名称等数据到VO
//             for (Bill bill : billList) {
//                 billVoList.add(this.bindBillStatuName(bill));
//             }
//             billPage.setRecords(billVoList);
//             return billPage;
//         } catch (BaseException e) {
//             LOGGER.error("/BillServiceImpl selectIncomingPage ERROR: {}", e.getMessage());
//             throw e;
//         } catch (Exception e) {
//             LOGGER.error("/BillServiceImpl selectIncomingPage ERROR: {}", e.getMessage());
//             throw new BaseException("查询失败");
//         }

        // JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
        //查询账单信息
        Page<BillVO> billPage = new Page<>();
        EntityWrapper entityWrapper = bindIncomingContition(inPage.getCondition());
        List<Bill> billList = baseMapper.selectPage(inPage.setCondition(Maps.newHashMap()), entityWrapper);
        BeanUtils.copyProperties(inPage, billPage);
        List<BillVO> billVoList = Lists.newArrayList();
        //绑定状态名称等数据到VO
        for (Bill bill : billList) {
            billVoList.add(this.bindBillStatuName(bill));
        }
        billPage.setRecords(billVoList);
        return billPage;
    }

    /**
     * 新增
     *
     * @param bill
     * @return
     */
    @Override
    public Bill insertBillOne(Bill bill) {
        try {
            bill.setBillCode(codeUtil.getBillCode().getNextCode(null));
            bill.setGmtCreate(new Date());
            if (bill.getIsDelete() == null) {
                bill.setIsDelete(0);
            }
            this.insert(bill);
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            throw new BaseException("新增账单错误");
        }
        return bill;
    }

    /**
     * 应付账单分页数据
     *
     * @param inPage
     * @return
     */
    @Override
    public Page<BillVO> selectPurchasePage(Page<Bill> inPage) {
        // try {
        //     Page<BillVO> billPage = new Page<>();
        //     EntityWrapper<Bill> entityWrapper = bindPurchaseContition(inPage.getCondition());
        //     entityWrapper.orderBy("gmt_create desc, id desc");
        //     List<Bill> billList = baseMapper.selectPage(inPage.setCondition(Maps.newHashMap()), entityWrapper);
        //     BeanUtils.copyProperties(inPage, billPage);
        //     List<BillVO> billVoList = Lists.newArrayList();
        //     for (Bill bill : billList) {
        //         billVoList.add(this.bindBillStatuName(bill));
        //     }
        //     billPage.setRecords(billVoList);
        //     return billPage;
        // } catch (BaseException e) {
        //     LOGGER.error("BillServiceImpl selectIncomingPage ERROR: {}", e.getMessage());
        //     throw e;
        // } catch (Exception e) {
        //     LOGGER.error("BillServiceImpl selectIncomingPage ERROR: {}", e.getMessage());
        //     throw new BaseException("查询失败");
        // }
        Page<BillVO> billPage = new Page<>();
        EntityWrapper<Bill> entityWrapper = bindPurchaseContition(inPage.getCondition());
        entityWrapper.orderBy("gmt_create desc, id desc");
        List<Bill> billList = baseMapper.selectPage(inPage.setCondition(Maps.newHashMap()), entityWrapper);
        BeanUtils.copyProperties(inPage, billPage);
        List<BillVO> billVoList = Lists.newArrayList();
        for (Bill bill : billList) {
            billVoList.add(this.bindBillStatuName(bill));
        }
        billPage.setRecords(billVoList);
        return billPage;
    }

    /**
     * 获取支付申请对应的应付出账
     *
     * @param payId
     * @return
     */
    @Override
    public List<Bill> queryBillPurchaseList(Long payId) {
        if (ObjectUtils.isEmpty(payId)) {
            return null;
        }
        List<PayApplyDtlBill> payApplyDtlBills = payApplyDtlBillService.queryPayApplyDtlBillList(payId);
        if (ObjectUtils.isEmpty(payApplyDtlBills)) {
            return null;
        }

        List<Long> billIds = Lists.newArrayList();
        payApplyDtlBills.forEach(payApplyDtlBill -> {
            billIds.add(payApplyDtlBill.getBilId());
        });
        if (CollectionUtils.isEmpty(billIds)) {
            return null;
        }
        EntityWrapper ew = new EntityWrapper<>();
        ew.in("id", billIds);
        return this.selectList(ew);
    }

    /**
     * 应收账单数据集合
     *
     * @param condition
     * @return
     */
    @Override
    public List<BillVO> selectIncomingList(Map<String, Object> condition) {
        // try {
        //     List<Bill> billList = baseMapper.selectList(bindIncomingContition(condition));
        //     List<BillVO> billVoList = Lists.newArrayList();
        //     for (Bill bill : billList) {
        //         billVoList.add(this.bindBillStatuName(bill));
        //     }
        //     return billVoList;
        // } catch (BaseException e) {
        //     LOGGER.error("BillServiceImpl selectIncomingList ERROR: {}", e.getMessage());
        //     throw e;
        // } catch (Exception e) {
        //     LOGGER.error("BillServiceImpl selectIncomingList ERROR: {}", e.getMessage());
        //     throw new BaseException("查询失败");
        // }
        List<Bill> billList = baseMapper.selectList(bindIncomingContition(condition));
        List<BillVO> billVoList = Lists.newArrayList();
        for (Bill bill : billList) {
            billVoList.add(this.bindBillStatuName(bill));
        }
        return billVoList;
    }

    /**
     * 应付账单数据集合
     *
     * @param condition
     * @return
     */
    @Override
    public List<BillVO> selectPurchaseList(Map<String, Object> condition) {
        // try {
        //     List<Bill> billList = baseMapper.selectList(bindPurchaseContition(condition));
        //     List<BillVO> billVoList = Lists.newArrayList();
        //     for (Bill bill : billList) {
        //         billVoList.add(this.bindBillStatuName(bill));
        //     }
        //     return billVoList;
        // } catch (BaseException e) {
        //     LOGGER.error("BillServiceImpl selectIncomingList ERROR: {}", e.getMessage());
        //     throw e;
        // } catch (Exception e) {
        //     LOGGER.error("BillServiceImpl selectIncomingList ERROR: {}", e.getMessage());
        //     throw new BaseException("查询失败");
        // }
        List<Bill> billList = baseMapper.selectList(bindPurchaseContition(condition));
        List<BillVO> billVoList = Lists.newArrayList();
        for (Bill bill : billList) {
            billVoList.add(this.bindBillStatuName(bill));
        }
        return billVoList;
    }

    /**
     * 绑定收入账单查询信息
     *
     * @param condition
     * @return
     */
    private EntityWrapper bindIncomingContition(Map<String, Object> condition) {
        EntityWrapper<Bill> ew = new EntityWrapper();
        //固定查询应收账单
        ew.orderBy("gmt_create desc, id desc");
        ew.eq("bill_type", 10);
        if (!CollectionUtils.isEmpty(condition)) {
            for (Map.Entry<String, Object> entry :
                    condition.entrySet()) {
                if (!Strings.isNullOrEmpty(entry.getKey())) {
                    if ("billCode".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("bill_code", entry.getValue());
                    }
                    if ("billStatus".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("bill_status", entry.getValue());
                    }
                    if ("customer".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("payer_id", entry);
                    }
                    if ("orderDateBegin".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.ge("order_date", entry);
                    }
                    if ("orderDateEnd".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.le("order_date", entry);
                    }
                }
            }
        }
        ew.andNew().eq("is_delete", 0).or().isNull("is_delete");
        return ew;
    }

    /**
     * 绑定支出账单查询信息
     *
     * @param condition
     * @return
     */
    private EntityWrapper bindPurchaseContition(Map<String, Object> condition) {
        EntityWrapper<Bill> ew = new EntityWrapper();
        //固定查询应收账单
        ew.orderBy("gmt_create desc, id desc");
        ew.eq("bill_type", 20);

        if (StringUtils.isEmpty(condition.get("billStatus"))) {
            ew.ne("bill_status", "50");
        } else {
            ew.eq("bill_status", condition.get("billStatus"));
        }
        if (!CollectionUtils.isEmpty(condition)) {
            for (Map.Entry<String, Object> entry :
                    condition.entrySet()) {
                if (Objects.nonNull(entry.getKey())) {
                    if ("billCode".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.like("bill_code", entry.getValue() + "");
                    }
                    if ("customer".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("payee_id", entry.getValue());
                    }
                    if ("payerId".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("payer_id", entry.getValue());
                    }
                    if ("payerName".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("payer_name", entry.getValue());
                    }
                    if ("orderDateBegin".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.ge("order_date", entry.getValue());
                    }
                    if ("orderDateEnd".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.le("order_date", entry.getValue());
                    }
                    if ("billProperty".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("bill_property", entry.getValue());
                    }
                    if ("isLock".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.eq("is_lock", entry.getValue());
                    }
                    if ("createUser".equals(entry.getKey()) && !StringUtils.isEmpty(entry.getValue())) {
                        ew.in("create_user", new Object[]{entry.getValue(), "系统"});
                    }
                }
            }
        }
        ew.andNew().eq("is_delete", 0).or().isNull("is_delete");
        return ew;
    }

    /**
     * 获取对比后的应收账单信息
     *
     * @param page
     * @return
     */
    @Override
    public Page<BillReconciliationVO> queryReconciliationPage(Page page) {
        Page<BillReconciliationVO> billReconciliationVOPage = new Page<>();
        if (Objects.nonNull(page) && Objects.nonNull(page.getCondition().get("billId"))) {
            //根据id号获取客户账单详明
            Long id = Long.valueOf(page.getCondition().get("billId").toString());
            Page<BillIoDetail> ioDetailPage = billIoDetailService.queryBillIoDetailPage(page, id);
            //保存分页数据
            if (Objects.nonNull(ioDetailPage)) {
                BeanUtils.copyProperties(ioDetailPage, billReconciliationVOPage);
            }

            billReconciliationVOPage.setRecords(bindBillIoDetailReconciliation(ioDetailPage.getRecords(), false));
        }
        return billReconciliationVOPage;
    }

    /**
     * 获取对比后的所有应收账单列表信息
     *
     * @param billId
     * @return
     */
    @Override
    public List<BillReconciliationVO> queryReconciliationList(Long billId) {
        List<BillReconciliationVO> billReconciliationVOS = Lists.newArrayList();
        if (!Objects.isNull(billId)) {
            List<BillIoDetail> billIoDetails = billIoDetailService.queryBillIoDetailList(Long.valueOf(billId));
            billReconciliationVOS = bindBillIoDetailReconciliation(billIoDetails, false);
        }
        return billReconciliationVOS;
    }

    /**
     * 获取对比后的应收账单列表信息
     *
     * @param billId
     * @param billIoDetails
     * @return
     */
    @Override
    public BillReconciliationAndSunVO queryReceivableReconciliation(String billId, List<BillIoDetail> billIoDetails) {
        try {
            BillReconciliationAndSunVO billReconciliationAndSunVO = new BillReconciliationAndSunVO();
            List<String> checkCloumns = new ArrayList<>();
            checkCloumns.add("actualAmt");
            checkCloumns.add("fare");
            checkCloumns.add("actualPrice");
            checkCloumns.add("kilometre");
            checkCloumns.add("otherMoney");
            int size = 0;
            int dtlSize = billIoDetails.size();
            BigDecimal price = new BigDecimal(0);

            int nThread = 0;
            if (dtlSize <= 500) {
                nThread = 1;
            } else if (dtlSize <= 1000) {
                nThread = 2;
            } else if (dtlSize <= 1500) {
                nThread = 3;
            } else if (nThread <= 2000) {
                nThread = 4;
            } else {
                nThread = 5;
            }
            ExecutorService executorService1 = Executors.newFixedThreadPool(nThread);
            int remaider = dtlSize % nThread;  //(先计算出余数)
            int number = dtlSize / nThread;  //然后是商
            int offset = 0;//偏移量

            try {
                for (int i = 0; i < nThread; i++) {
                    // 先分组
                    if (remaider > 0) {
                        List<BillIoDetail> enrollList = billIoDetails.subList(i * number + offset, (i + 1) * number + offset + 1);
                        executorService1.execute(() -> {
                            dealBillDetailData(billId, enrollList, price, checkCloumns, billReconciliationAndSunVO);
                        });
                        remaider--;
                        offset++;
                    } else {
                        List<BillIoDetail> enrollList = billIoDetails.subList(i * number + offset, (i + 1) * number + offset);
                        executorService1.execute(() -> {
                            dealBillDetailData(billId, enrollList, price, checkCloumns, billReconciliationAndSunVO);
                        });
                    }
                }
                executorService1.shutdown();
                while (!executorService1.awaitTermination(60, TimeUnit.SECONDS)) {
                    LOGGER.info("线程池没有关闭");
                }
                LOGGER.info("线程池已经关闭");
            } catch (Exception ex) {
                LOGGER.error("updateBill: {}", ex);
                throw new BaseException(ex.getMessage());
            }

            // dealBillDetailData(billId, billIoDetails, price, checkCloumns, billReconciliationAndSunVO);

            billReconciliationAndSunVO.setPrice(price);
            // billReconciliationAndSunVO.setSize(size);
            billReconciliationAndSunVO.setSize(billIoDetails.size());
            List<BillReconciliationVO> billReconciliationVOList = billReconciliationAndSunVO.getBillReconciliationVOs();
            if (CollectionUtils.isEmpty(billReconciliationVOList)) {
                billReconciliationAndSunVO.setErrorSize(0);
            } else {
                billReconciliationAndSunVO.setErrorSize(billReconciliationAndSunVO.getBillReconciliationVOs().size());
            }
            billReconciliationAndSunVO.setSuccessSize(dtlSize - billReconciliationAndSunVO.getErrorSize());
            return billReconciliationAndSunVO;
        } catch (Exception e) {
            throw new BaseException("对比账单失败");
        }
    }

    private void dealBillDetailData(String billId, List<BillIoDetail> billIoDetails,
                                    BigDecimal price, List<String> checkCloumns,
                                    BillReconciliationAndSunVO billReconciliationAndSunVO) {
        Map<String, BillIoDetail> billDetailMap = createBillDetailMap(billId, billIoDetails);
        try {

            for (BillIoDetail billIoDetail : billIoDetails) {
                /*
                 * 根据公里数和单价计算总金额
                 */
                BigDecimal kilometre = billIoDetail.getKilometre();
                BigDecimal actualPrice = billIoDetail.getActualPrice();
                BigDecimal otherMoney = billIoDetail.getOtherMoney();
                if (kilometre == null) {
                    kilometre = BigDecimal.ZERO;
                }
                if (actualPrice == null) {
                    actualPrice = BigDecimal.ZERO;
                }
                if (otherMoney == null) {
                    otherMoney = BigDecimal.ZERO;
                }
                // 合计进行四舍五入
                // billIoDetail.setActualAmt(kilometre.multiply(actualPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
                billIoDetail.setFare(kilometre.multiply(actualPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
                billIoDetail.setActualAmt(billIoDetail.getFare().add(otherMoney));

                /*
                 * 寻找对应账单
                 */
                // EntityWrapper<BillIoDetail> objectEntityWrapper = new EntityWrapper<>();
                // objectEntityWrapper.eq("head_id", billId);
                // objectEntityWrapper.eq("ship_code", billIoDetail.getShipCode());
                // objectEntityWrapper.eq("cost_name", billIoDetail.getCostName());
                // BillIoDetail billIoDetail1 = billIoDetailService.selectOne(objectEntityWrapper);
                BillIoDetail billIoDetail1 = billDetailMap.get(billIoDetail.getShipCode() + "-" + billIoDetail.getCostName());
                /*
                 * 对比结果
                 */
                String msg = "";
                List<String> neColumns;
                if (billIoDetail1 == null) {
                    msg = "对账单不存在";
                    neColumns = new ArrayList<>();
                } else {
                    billIoDetail.setId(billIoDetail1.getId());
                    neColumns = new BeanColumnUtil<BillIoDetail, BillIoDetail>().checkColumnInAppoint(billIoDetail, billIoDetail1, checkCloumns);
                    msg = bindCheckMessage(neColumns, BeanColumnUtil.objectToMap(billIoDetail), BeanColumnUtil.objectToMap(billIoDetail1), true);
                }
                /*
                 * 保存对比后的信息
                 */
                // size++;
                if (Objects.nonNull(billIoDetail.getActualAmt()) && billIoDetail.getActualAmt().compareTo(new BigDecimal(0)) != 0) {
                    price = price.add(billIoDetail.getActualAmt());
                }
                if (!StringUtils.isEmpty(msg)) {
                    BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
                    billReconciliationVO.setNeCloumns(neColumns);

                    billReconciliationVO.setMessage(msg);
                    billReconciliationVO.setBillIoDetail(billIoDetail);
                    billReconciliationVO.setBillId(billId);
                    billReconciliationAndSunVO.addBillReconciliationVO(billReconciliationVO);
                }
            }
            billDetailMap = null;
        } catch (Exception e) {
            throw new BaseException("对比账单失败");
        } finally {
            billDetailMap = null;
        }
    }

    private Map<String, BillIoDetail> createBillDetailMap(String billId, List<BillIoDetail> detailList) {
        Map<String, BillIoDetail> detailMap = Maps.newHashMap();
        List<String> shipCodeList = Lists.newArrayList();
        detailList.forEach(detail -> {
            shipCodeList.add(detail.getShipCode());
        });
        EntityWrapper<BillIoDetail> objectEntityWrapper = new EntityWrapper<>();
        objectEntityWrapper.eq("head_id", billId);
        objectEntityWrapper.in("ship_code", shipCodeList);
        List<BillIoDetail> billIoDetailList = billIoDetailService.selectList(objectEntityWrapper);
        if (!CollectionUtils.isEmpty(billIoDetailList)) {
            billIoDetailList.forEach(billIoDetail -> {
                detailMap.put(billIoDetail.getShipCode() + "-" + billIoDetail.getCostName(), billIoDetail);
            });
        }
        return detailMap;
    }


    /**
     * 获取绑定的应付对应账单
     *
     * @param customerBillVOS
     * @param isBindReceivable
     * @return
     */
    @Override
    public List<BillReconciliationVO> queryPayableReconciliationList(List<CustomerBillVO> customerBillVOS, String billId, boolean bingUnCheckFee, boolean isBindReceivable) {
        List<BillReconciliationVO> returnVal = new ArrayList<>();
        if (!CollectionUtils.isEmpty(customerBillVOS)) {

            List<BillReconciliationVO> nullMsg = new ArrayList<>();
            List<FeePayable> feePayables = null;
            Map<String, FeePayable> feePayableHashMap = new HashMap<>();

            //获取所有可对比列
            List<Object> feeIdsObj = null;
            List<Long> feeIds = new ArrayList<>();
            if (!Strings.isNullOrEmpty(billId)) {
                EntityWrapper<BillDetail> billDetailEntityWrapper = new EntityWrapper<>();
                billDetailEntityWrapper.eq("bill_id", billId);
                billDetailEntityWrapper.setSqlSelect("fee_id");
                feeIdsObj = billDetailService.selectObjs(billDetailEntityWrapper);
            }
            //验证数据数量判断或取对应数据的方式（false --> 对比数量少于一半  true --> 大于一半）
            Boolean bindFeeType = (CollectionUtils.isEmpty(feeIdsObj) ? null : (feeIdsObj.size() / 2) < customerBillVOS.size());

            //全部获取后天标识转换
            if (bindFeeType == null ? false : bindFeeType) {
                feeIdsObj.forEach(o -> feeIds.add((Long) o));
                feePayables = feePayableService.selectBatchIds(feeIds);
                if (!CollectionUtils.isEmpty(feePayables)) {
                    feePayables.forEach(feePayable -> {
                        feePayableHashMap.put(feePayable.getWaybillDtlId(), feePayable);
                    });
                }
            }

            //遍历存储剩余数据
            for (CustomerBillVO customerBillVO :
                    customerBillVOS) {
                BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
                if (customerBillVO.getActualAmt() == null) {
                    customerBillVO.setActualPrice(customerBillVO.getActualPrice() == null ? BigDecimal.ZERO : customerBillVO.getActualPrice());
                    customerBillVO.setKilometre(customerBillVO.getKilometre() == null ? "0" : customerBillVO.getKilometre());
                    customerBillVO.setActualAmt(customerBillVO.getActualPrice().multiply(new BigDecimal(customerBillVO.getKilometre())));
                }
                if (bindFeeType != null) {
                    if (bindFeeType) {
                        billReconciliationVO.setFeePayable(feePayableHashMap.get(customerBillVO.getWaybillDtlId()));
                    } else {
                        EntityWrapper<FeePayable> ew = new EntityWrapper<>();
                        ew.eq("waybill_dtl_id", customerBillVO.getWaybillDtlId());
                        if (!CollectionUtils.isEmpty(feeIds)) {
                            ew.in("id", feeIds);
                        }
                        billReconciliationVO.setFeePayable(feePayableService.selectOne(ew));
                    }
                }
                billReconciliationVO.setBillId(billId);
                billReconciliationVO.setCustomerBillVO(customerBillVO);

                this.billReconciliation(billReconciliationVO, true, false);
                if (billReconciliationVO != null) {
                    if (ArrayUtils.isEmpty(billReconciliationVO.getMessageList())) {
                        nullMsg.add(billReconciliationVO);
                    } else {
                        returnVal.add(billReconciliationVO);
                    }
                }
            }
            returnVal.addAll(nullMsg);
        }
        return returnVal;
    }


    /**
     * 获取账单头信息
     *
     * @param billIoId
     * @return
     */
    @Override
    public BillHeaderVO queryBillHeader(String billIoId) {
        BillHeaderVO billHeaderVO = new BillHeaderVO();

        BillIo billIo = billIoService.selectById(billIoId);
        if (Objects.isNull(billIo)) {
            throw new BaseException("客户账单不存在");
        }
        billHeaderVO.setBillIo(billIo);
        EntityWrapper<Bill> billEw = new EntityWrapper<>();
        billEw.eq("customer_bill_id", billIoId);
        List<Bill> bill = baseMapper.selectList(billEw);
        if (CollectionUtils.isEmpty(bill)) {
            throw new BaseException("应收账单不存在");
        }
        billHeaderVO.setBill(bill.get(0));
        return billHeaderVO;
    }

    /**
     * 账单异常回调数据处理
     *
     * @param billId
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void billErrorCallback(String billId, List<BillReconciliationVO> billReconciliationVOS) {
        //验证对应账单信息
        CustBillDTO custBillDTO = new CustBillDTO();
        BillIo billIo = billIoService.selectById(billId);
        if (Objects.isNull(billIo)) {
            throw new BaseException("客户账单不存在");
        }
        if ("30".equals(billIo.getBillStatus())) {
            throw new BaseException("该客户账单已被确认，无法重复确认");
        }
        //验证登陆人tenantId
        JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
        if (ObjectUtils.isEmpty(jwtAccountVO)) {
            throw new BaseException("未获取到登录信息");
        }

        //保存异常对账基本信息
        custBillDTO.setBillId(billIo.getBillCode());// 账单编码
        custBillDTO.setBillStatus(3);// 账单状态（1 对账不平 3 对账成功）
        custBillDTO.setContNum(billIo.getNum());// 对账总数量
        custBillDTO.setContTotal(String.valueOf(billIo.getGrossAmt()));//账单总金额
        custBillDTO.setUploadTime(new Date());// 账单的对账时间
        custBillDTO.setUploadUser(jwtAccountVO.getAccountId());// 账单对账操作人
        List<CustBillDetailDTO> custBillDetailDTOS = Lists.newArrayList();


        //获取对应账款信息并绑定对应对账结果
        if (CollectionUtils.isEmpty(billReconciliationVOS)) {
            billReconciliationVOS = Lists.newArrayList();
        }

        buildBillIoDetailList(billIo.getId(), billReconciliationVOS);
        // List<BillIoDetail> billIoDetails = billIoDetailService.getBillIoDetailByHeadId(billIo.getId());
        // if (CollectionUtils.isEmpty(billReconciliationVOS)) {
        //     billReconciliationVOS = Lists.newArrayList();
        //
        //     //遍历存储剩余数据
        //     // billReconciliationVOS = bindBillIoDetailReconciliation(billIoDetails, true);
        //     if (!CollectionUtils.isEmpty(billIoDetails)) {
        //         for (BillIoDetail billIoDetail : billIoDetails) {
        //             BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
        //             billReconciliationVO.setBillIoDetail(billIoDetail);
        //             billReconciliationVOS.add(billReconciliationVO);
        //         }
        //     }
        // } else {
        //     // 非对账数据
        //     Set<String> shipCodeAndCostName = new HashSet<>();
        //     billReconciliationVOS.forEach(billReconciliationVO -> {
        //         BillIoDetail billIoDetail = billReconciliationVO.getBillIoDetail();
        //         if (Objects.nonNull(billIoDetail)) {
        //             shipCodeAndCostName.add(billIoDetail.getShipCode() + "-" + billIoDetail.getCostName());
        //         }
        //     });
        //     if (!CollectionUtils.isEmpty(billIoDetails)) {
        //         for (BillIoDetail billIoDetail : billIoDetails) {
        //             if (!shipCodeAndCostName.contains((billIoDetail.getShipCode() + "-" + billIoDetail.getCostName()))) {
        //                 BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
        //                 billReconciliationVO.setBillIoDetail(billIoDetail);
        //                 billReconciliationVOS.add(billReconciliationVO);
        //             }
        //         }
        //     }
        // }


        //将对帐的详明账款信息拼入异常对账的详明中
        List<ExceptionBillDtl> exceptionBillList = Lists.newArrayList();
        final BigDecimal[] totalSum = {BigDecimal.ZERO};
        billReconciliationVOS.forEach(billReconciliationVO -> {
            CustBillDetailDTO custBillDetailDTO = new CustBillDetailDTO();
            BillIoDetail billIoDetail = billReconciliationVO.getBillIoDetail();
            custBillDetailDTO.setId(billIoDetail.getId());
            custBillDetailDTO.setMiles(billIoDetail.getKilometre());//计费公里数
            custBillDetailDTO.setCarTypeName(billIoDetail.getVehicleTypeName());//商品车型名称
            custBillDetailDTO.setId(billIoDetail.getId());//承运商对账明细单id
            custBillDetailDTO.setInsertTime(billIoDetail.getGmtCreate());//创建时间
            custBillDetailDTO.setPrice(billIoDetail.getActualPrice());//计费单价
            custBillDetailDTO.setShipEndAddr(billIoDetail.getEndAddr());//目的地
            custBillDetailDTO.setShipStartAddr(billIoDetail.getStartAddr());//起运地
            custBillDetailDTO.setShipNum(billIoDetail.getNum());//数量
            custBillDetailDTO.setCustWaybillId(billIoDetail.getCustomerCode());//数量
            custBillDetailDTO.setSumMoney(billIoDetail.getActualAmt());//总金额
            custBillDetailDTO.setSysWaybillId(billIoDetail.getShipCode());//系统运单id
            custBillDetailDTO.setTransModeId(billIoDetail.getTransModel());//运输模式
            custBillDetailDTO.setVin(billIoDetail.getVin());//vin码
            custBillDetailDTO.setUploadTime(billIoDetail.getGmtModify());//对账时间
            // 运输费
            custBillDetailDTO.setFare(billIoDetail.getFare());
            // 其他费用
            custBillDetailDTO.setOtherMoney(billIoDetail.getOtherMoney());
            custBillDetailDTOS.add(custBillDetailDTO);
//            if (Objects.isNull(billReconciliationVO.getFeeReceivable()) || Objects.isNull(billReconciliationVO.getFeeReceivable().getId())) {
//                custBillDTO.setBillStatus(1);
//            } else
            if (!Strings.isNullOrEmpty(billReconciliationVO.getMessage())) {
                custBillDTO.setBillStatus(1);
                custBillDetailDTO.setErrorMsg(billReconciliationVO.getMessage());//异常描述信息
                // 账单明细异常
                ExceptionBillDtl exceptionBill = new ExceptionBillDtl();
                exceptionBill.setBillId(billIoDetail.getId());
                exceptionBill.setErrorMessage(billReconciliationVO.getMessage());
                exceptionBill.setHeadId(billIoDetail.getHeadId());
                exceptionBill.setIsError(1);//是否有误：0、否 1、是
//                exceptionBill.setOrderCode(billReconciliationVO.getFeeReceivable().getOrderCode());//订单号
//                exceptionBill.setOrderCodeDtl(billReconciliationVO.getFeeReceivable().getOrderDtlId() + "");//订单明细id
                //exceptionBill.setShipDetailId(billIoDetail.getShipDtlId());//运单明细
                exceptionBill.setShipDetailId(billIoDetail.getShipCode());//运单明细
//                exceptionBill.setWaybillId(billIoDetail.getShipCode());//运单号
                exceptionBillList.add(exceptionBill);
            }
            billReconciliationVO.getMessage();
            if (billIoDetail.getActualAmt() != null) {
                totalSum[0] = totalSum[0].add(billIoDetail.getActualAmt());
            }
        });
        //账单总金额 - 采用明细金额累加
        custBillDTO.setContTotal(String.valueOf(totalSum[0]));
        if (custBillDTO.getBillStatus() == 1) {//60
            //账单异常
            EntityWrapper<ExceptionBill> oldWapper = new EntityWrapper<>();
            ExceptionBill exceptionBill = new ExceptionBill();
            exceptionBill.setBillCode(billIo.getBillCode());
            //对应客户账单ID,AR(10)应收账单 ， AP(20)应付账单
            exceptionBill.setBillId(billIo.getId());
            oldWapper.eq("bill_id", billIo.getId());
            if (billIo.getBillType().equals(INCOME_BILL)) {//应收账单
//                exceptionBill.setBillId(billIo.getPayerId());//客户=付款方
                exceptionBill.setBillTyep("10");
                oldWapper.eq("bill_tyep", 10);
            } else if (billIo.getBillType().equals(PAYMENT_BILL)) {//应付账单
//                exceptionBill.setBillId(billIo.getPayeeId());//客户=收款方
                exceptionBill.setBillTyep("20");
                oldWapper.eq("bill_tyep", 20);
            }
            exceptionBill.setCreator(billIo.getCreator());
            exceptionBill.setGmtCreate(billIo.getGmtCreate());
            exceptionBill.setIsUploading(1);//是否上传
            exceptionBillService.delete(oldWapper);
            exceptionBillService.insertExceptionBill(exceptionBill);
            // 账单明细异常
            if (!exceptionBillList.isEmpty()) {
                exceptionBillDtlService.insertExceptionBillDtl(exceptionBillList, exceptionBill.getId());
            }
            //set账单类型
            billIoService.updateBillIo(billIo.getBillCode(), "60", billIo.getBillType());
            this.updateBillIo(billIo.getBillCode(), "60");
        } else if (custBillDTO.getBillStatus() == 3) {//30
            billIoService.updateBillIo(billIo.getBillCode(), "30", billIo.getBillType());
            this.updateBillIo(billIo.getBillCode(), "30");
        }

        custBillDTO.setCustBillDetailList(custBillDetailDTOS);
        // String jsonString = JSONObject.toJSONString(custBillDTO);
        LOGGER.info("Resource billContrastResult --> {}", custBillDTO.toString());
        String contrastResult = otmUtil.billContrastResult(custBillDTO);
    }

    private void buildBillIoDetailList(Long billId, List<BillReconciliationVO> billReconciliationVoList) {
        List<BillIoDetail> billIoDetails = billIoDetailService.getBillIoDetailByHeadId(billId);
        if (CollectionUtils.isEmpty(billReconciliationVoList)) {
            if (!CollectionUtils.isEmpty(billIoDetails)) {
                for (BillIoDetail billIoDetail : billIoDetails) {
                    BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
                    billReconciliationVO.setBillIoDetail(billIoDetail);
                    billReconciliationVoList.add(billReconciliationVO);
                }
            }
        } else {
            // 非对账数据
            Set<String> shipCodeAndCostName = new HashSet<>();
            billReconciliationVoList.forEach(billReconciliationVO -> {
                BillIoDetail billIoDetail = billReconciliationVO.getBillIoDetail();
                if (Objects.nonNull(billIoDetail)) {
                    shipCodeAndCostName.add(billIoDetail.getShipCode() + "-" + billIoDetail.getCostName());
                }
            });
            if (!CollectionUtils.isEmpty(billIoDetails)) {
                for (BillIoDetail billIoDetail : billIoDetails) {
                    if (!shipCodeAndCostName.contains((billIoDetail.getShipCode() + "-" + billIoDetail.getCostName()))) {
                        BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
                        billReconciliationVO.setBillIoDetail(billIoDetail);
                        billReconciliationVoList.add(billReconciliationVO);
                    }
                }
            }
        }
    }

    /**
     * 应付账单确认
     *
     * @param billId
     */
    @Override
    public void payableBillConfirm(String billId) {
        Bill bill = this.selectById(billId);
        if (Objects.isNull(bill)) {
            throw new BaseException("客户账单不存在");
        }
        if ("10".equals(bill.getBillStatus()) || "60".equals(bill.getBillStatus())) {
            bill.setBillStatus("30");
        } else {
            throw new BaseException("该客户账单已无法确认");
        }
        this.updateById(bill);
    }

    /**
     * 应付账单异常
     *
     * @param billReconciliationVOS
     * @param billId
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void payableBillException(List<BillReconciliationVO> billReconciliationVOS, String billId) {
        Bill bill = this.selectById(billId);
        if (Objects.isNull(bill)) {
            throw new BaseException("账单不存在");
        }
        if (CollectionUtils.isEmpty(billReconciliationVOS)) {
            throw new BaseException("请提交异常信息");
        }
        //账单异常
        ExceptionBill exceptionBill = new ExceptionBill();
        exceptionBill.setBillId(bill.getId());//客户=收款方
        exceptionBill.setBillTyep(bill.getBillCode());
        exceptionBill.setCreator(bill.getCreator());
        exceptionBill.setIsUploading(1);//是否上传
        exceptionBillService.insertExceptionBill(exceptionBill);

        List<ExceptionBillDtl> exceptionBillDtls = new ArrayList<>();
        billReconciliationVOS.forEach(billReconciliationVO -> {
            FeePayable feePayable = billReconciliationVO.getFeePayable();
            if (!Strings.isNullOrEmpty(billReconciliationVO.getMessage())) {
                // 账单明细异常
                ExceptionBillDtl exceptionBillDtl = new ExceptionBillDtl();
                exceptionBillDtl.setBillId(bill.getId());
                exceptionBillDtl.setErrorMessage(billReconciliationVO.getMessage());
                exceptionBillDtl.setHeadId(exceptionBill.getId());
                exceptionBillDtl.setIsError(1);//是否有误：0、否 1、是
                exceptionBillDtl.setOrderCode(feePayable.getOrderCode());//订单号
                exceptionBillDtl.setOrderCodeDtl(feePayable.getOrderDtlId() + "");//订单明细id
//                exceptionBillDtl.setShipDetailId(feePayable.getShipDtlId());//运单明细
                exceptionBillDtl.setWaybillId(feePayable.getWaybillId());//运单号
                exceptionBillDtl.setWaybillDetailId(feePayable.getWaybillDtlId());//运单号
                exceptionBillDtls.add(exceptionBillDtl);
            }
            billReconciliationVO.getMessage();
        });
        // 账单明细异常
        if (!exceptionBillDtls.isEmpty()) {
            exceptionBillDtlService.insertExceptionBillDtl(exceptionBillDtls);
        }
        //set账单类型
        bill.setBillStatus("60");
        this.updateById(bill);
    }

    private List<BillReconciliationVO> bindBillIoDetailReconciliation(List<BillIoDetail> billIoDetails, boolean bindCloumns) {
        List<BillReconciliationVO> billReconciliationVOs = new ArrayList<>();

        if (!CollectionUtils.isEmpty(billIoDetails)) {
            List<String> wayBillDtlIds = new ArrayList<>();
            Map<String, FeeReceivable> billIoDetailMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(billIoDetails)) {
                billIoDetails.forEach(billIoDetail -> {
                    wayBillDtlIds.add(billIoDetail.getShipCode());
                });
            }
            EntityWrapper<FeeReceivable> ew = new EntityWrapper<>();
            ew.in("waybill_dtl_id", wayBillDtlIds);
//            if (!CollectionUtils.isEmpty(feeIds)) {
//                ew.in("id", feeIds);
//            }
            List<FeeReceivable> feeReceivables = feeReceivableService.selectList(ew);
            if (!CollectionUtils.isEmpty(feeReceivables)) {
                feeReceivables.forEach(feeReceivable -> billIoDetailMap.put(feeReceivable.getWaybillDtlId(), feeReceivable));
            }
            for (BillIoDetail billIoDetail : billIoDetails) {
                BillReconciliationVO billReconciliationVO = new BillReconciliationVO();
                billReconciliationVO.setBillIoDetail(billIoDetail);
                billReconciliationVO.setFeeReceivable(billIoDetailMap.get(billIoDetail.getShipCode()));
                billReconciliationVOs.add(this.billReconciliation(billReconciliationVO, false, bindCloumns));
            }
        }
        return billReconciliationVOs;
    }


    /**
     * 获取对账后的信息
     * 根据客户账单信息获取对应应收帐单对比数据结果
     *
     * @param billReconciliationVO 对账绑定对象
     * @param bindArePayable       是否是检查应付账单
     * @param bindCloumns          是否未msg绑定异常列名
     * @return
     */
    private BillReconciliationVO billReconciliation(BillReconciliationVO billReconciliationVO, boolean bindArePayable, boolean bindCloumns) {
        try {
            //设置对比的列
            List<String> checkCloumns = new ArrayList<>();
            checkCloumns.add("vehicleTypeCode");
            checkCloumns.add("startAddr");
            checkCloumns.add("endAddr");
            checkCloumns.add("num");
            checkCloumns.add("transModel");
            checkCloumns.add("actualPrice");
            checkCloumns.add("kilometre");
            checkCloumns.add("actualAmt");

            List<String> checkCloumns1 = new ArrayList<>(checkCloumns);
            checkCloumns1.add("startProvince");
            checkCloumns1.add("startCity");
            checkCloumns1.add("startCounty");
            checkCloumns1.add("endProvince");
            checkCloumns1.add("endCity");
            checkCloumns1.add("endCounty");

//            List<Long> feeIds = new ArrayList<>();
//            EntityWrapper<BillDetail> billDetailEntityWrapper = new EntityWrapper<>();
//            if (!Strings.isNullOrEmpty(billReconciliationVO.getBillId())) {
//                billDetailEntityWrapper.eq("bill_id", billReconciliationVO.getBillId());
//                List<BillDetail> billDetails = billDetailService.selectList(billDetailEntityWrapper);
//                for (BillDetail billDetail :
//                        billDetails) {
//                    feeIds.add(billDetail.getFeeId());
//                }
//            }
            //根据相同对应字段查找对应应收帐单
            if (bindArePayable) {
                CustomerBillVO customerBillVO = billReconciliationVO.getCustomerBillVO();
//                EntityWrapper<FeePayable> ew = new EntityWrapper<>();
//                //ew.eq("waybill_id", customerBillVO.getWaybillId());
//                ew.eq("waybill_dtl_id", customerBillVO.getWaybillDtlId());
//                if (!CollectionUtils.isEmpty(feeIds)) {
//                    ew.in("id", feeIds);
//                }
                FeePayable feePayable = billReconciliationVO.getFeePayable();
                if (Objects.nonNull(feePayable)) {
                    //检查字段值，并绑定对应提示信息
                    List<String> neColumns = new BeanColumnUtil<CustomerBillVO, FeePayable>().checkColumnInAppoint(customerBillVO, feePayable, checkCloumns1);
                    billReconciliationVO.setNeCloumns(neColumns);
                    Map<String, Object> customerMap = BeanColumnUtil.objectToMap(customerBillVO);
                    Map<String, Object> feePayableMap = BeanColumnUtil.objectToMap(feePayable);

                    if (CollectionUtils.isEmpty(neColumns)) {
                        billReconciliationVO.setMessage("成功");
                    } else {
                        //将实体map按<字段-值>方式传入异常转换方法并拼接值到对应位置
                        billReconciliationVO.setMessage(this.bindCheckMessage(neColumns, customerMap, feePayableMap, bindCloumns));
                    }
                } else {
                    billReconciliationVO.setMessage("无对应的详单信息！");
                }
            } else {
                BillIoDetail ioDetail = billReconciliationVO.getBillIoDetail();
//                EntityWrapper<FeeReceivable> ew = new EntityWrapper<>();
//                //ew.eq("waybill_id", ioDetail.getShipCode());
//                ew.eq("waybill_dtl_id", ioDetail.getShipCode());
//                if (!CollectionUtils.isEmpty(feeIds)) {
//                    ew.in("id", feeIds);
//                }
                FeeReceivable feeReceivable = billReconciliationVO.getFeeReceivable();
                if (Objects.nonNull(feeReceivable)) {
                    //检查字段值是否相同
                    List<String> neColumns = new BeanColumnUtil<BillIoDetail, FeeReceivable>().checkColumnInAppoint(ioDetail, feeReceivable, checkCloumns);
                    billReconciliationVO.setNeCloumns(neColumns);
                    //将实体转换成map
                    Map<String, Object> feeMap = BeanColumnUtil.objectToMap(feeReceivable);
                    Map<String, Object> billDetailMap = BeanColumnUtil.objectToMap(ioDetail);
                    //判断无匹配数据和无异常现象
                    if (CollectionUtils.isEmpty(neColumns)) {
                        billReconciliationVO.setMessage("成功");
                    } else {
                        //将实体map按<字段-值>方式传入异常转换方法并拼接值到对应位置
                        billReconciliationVO.setMessage(this.bindCheckMessage(neColumns, feeMap, billDetailMap, bindCloumns));
                    }
                } else {
                    billReconciliationVO.setMessage("客户对账明细数据【\" + " + ioDetail.getShipCode() + " + \"】无对应的详单信息！");
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
        //空结果处理
        if (Objects.isNull(billReconciliationVO.getFeeReceivable())) {
            billReconciliationVO.setFeeReceivable(new FeeReceivable());
        }
        if (Objects.isNull(billReconciliationVO.getBillIoDetail())) {
            billReconciliationVO.setBillIoDetail(new BillIoDetail());
        }
        if (Objects.isNull(billReconciliationVO.getCustomerBillVO())) {
            billReconciliationVO.setCustomerBillVO(new CustomerBillVO());
        }
        if (Objects.isNull(billReconciliationVO.getFeePayable())) {
            billReconciliationVO.setFeePayable(new FeePayable());
        }
        if (Objects.isNull(billReconciliationVO.getMessage())) {
            billReconciliationVO.setMessage("");
        }
        if (!Strings.isNullOrEmpty(billReconciliationVO.getMessage()) && !"成功".equals(billReconciliationVO.getMessage())) {
            billReconciliationVO.setMessageList(billReconciliationVO.getMessage().split(","));
        } else {
            billReconciliationVO.setMessageList(new String[0]);
        }
        if (Objects.isNull(billReconciliationVO.getNeCloumns())) {
            billReconciliationVO.setNeCloumns(Lists.newArrayList());
        }
        return billReconciliationVO;
    }

    /**
     * 绑定异常信息
     *
     * @param neColumns
     * @param map1
     * @param map2
     * @param canBindCloumns
     * @return
     */
    private String bindCheckMessage(List<String> neColumns, Map<String, Object> map1, Map<String, Object> map2, boolean canBindCloumns) {
        String msg = "";
        try {
            StringBuilder cloumBuilder = new StringBuilder();

            for (String column : neColumns) {
                if (!Strings.isNullOrEmpty(column)) {
                    String cloumnName = "";
                    String addMsg = "";
                    String costomentCloumnName = "";
                    if ("vehicleTypeName".equals(column)) {
                        cloumnName = "vehicleTypeName";
                        costomentCloumnName = "carTypeName";
                        addMsg = "对账单车型【XXX】不匹配详单车型【XXX】";
                    } else if ("startAddr".equals(column)) {
                        cloumnName = "startAddr";
                        costomentCloumnName = "shipStartAddr";
                        addMsg = "对账单运输起运地【XXX】不匹配详单运输起运地【XXX】";
                    } else if ("endAddr".equals(column)) {
                        cloumnName = "endAddr";
                        costomentCloumnName = "shipEndAddr";
                        addMsg = "对账单运输目的地【XXX】不匹配详单运输目的地【XXX】";
                    } else if ("num".equals(column)) {
                        cloumnName = "num";
                        costomentCloumnName = "shipNum";
                        addMsg = "对账单运输数量【XXX】不匹配详单运输数量【XXX】";
                    } else if ("transModel".equals(column)) {
                        cloumnName = "transModel";
                        costomentCloumnName = "transModeId";
                        addMsg = "对账单运输模式【XXX】不匹配详单运输模式【XXX】";
                    } else if ("actualPrice".equals(column)) {
                        cloumnName = "actualPrice";
                        costomentCloumnName = "price";
                        addMsg = "对账单单价【XXX】不匹配详单单价【XXX】";
                    } else if ("kilometre".equals(column)) {
                        cloumnName = "kilometre";
                        costomentCloumnName = "miles";
                        addMsg = "对账单公里数【XXX】不匹配详单公里数【XXX】";
                    } else if ("actualAmt".equals(column)) {
                        cloumnName = "actualAmt";
                        costomentCloumnName = "sumMoney";
                        addMsg = "对账单总金额【XXX】不匹配详单总金额【XXX】";
                    }
                    //省市区
                    else if ("startProvince".equals(column)) {
                        cloumnName = "startProvince";
                        costomentCloumnName = "startProvince";
                        addMsg = "对账单起运省【XXX】不匹配详单起运省【XXX】";
                    } else if ("startCity".equals(column)) {
                        cloumnName = "startCity";
                        costomentCloumnName = "startCity";
                        addMsg = "对账单起运市【XXX】不匹配详单起运市【XXX】";
                    } else if ("startCounty".equals(column)) {
                        cloumnName = "startCounty";
                        costomentCloumnName = "startCounty";
                        addMsg = "对账单起运区【XXX】不匹配详单起运区【XXX】";
                    } else if ("endProvince".equals(column)) {
                        cloumnName = "endProvince";
                        costomentCloumnName = "endProvince";
                        addMsg = "对账单目的省【XXX】不匹配详单目的省【XXX】";
                    } else if ("endCity".equals(column)) {
                        cloumnName = "endCity";
                        costomentCloumnName = "endCity";
                        addMsg = "对账单目的市【XXX】不匹配详单目的市【XXX】";
                    } else if ("endCounty".equals(column)) {
                        cloumnName = "endCounty";
                        costomentCloumnName = "endCounty";
                        addMsg = "对账单目的区【XXX】不匹配详单目的区【XXX】";
                    } else if ("otherMoney".equals(column)) {
                        cloumnName = "otherMoney";
                        costomentCloumnName = "otherMoney";
                        addMsg = "对账其他费用【XXX】不匹配详单其他费用【XXX】";
                    }

                    if (!(Strings.isNullOrEmpty(cloumnName) || Strings.isNullOrEmpty(addMsg))) {
                        //拼接分割字符
                        if (!Strings.isNullOrEmpty(msg) && !",".equals(msg.substring(msg.length() - 1, msg.length()))) {
                            msg += ",";
                        }
                        if (!CollectionUtils.isEmpty(map1) && Objects.nonNull(map1.get(cloumnName))) {
                            addMsg = addMsg.replaceFirst("XXX", String.valueOf(map1.get(cloumnName)));
                        } else {
                            addMsg = addMsg.replaceFirst("XXX", "");
                        }
                        if (!CollectionUtils.isEmpty(map2) && Objects.nonNull(map2.get(cloumnName))) {
                            addMsg = addMsg.replaceFirst("XXX", String.valueOf(map2.get(cloumnName)));
                        } else {
                            addMsg = addMsg.replaceFirst("XXX", "");
                        }
                        if (canBindCloumns) {
                            //addMsg = costomentCloumnName +"#"+ addMsg;
                            cloumBuilder.append(costomentCloumnName).append("/");
                        }
                        msg += addMsg;
                    }
                }
            }
            if (canBindCloumns) {
                if (!StringUtils.isEmpty(msg)) {
                    msg = cloumBuilder.substring(0, cloumBuilder.lastIndexOf("/")) + "#" + msg;
                }
            }
        } catch (Exception e) {
            throw new BaseException("创建导出信息错误");
        }
        return msg;
    }

    /**
     * 新增
     *
     * @param inbill 应收应付账单详情
     * @param ids    绑定的详明价格
     */
    @Override
    public void insertBillAndDetail(Bill inbill, List<Long> ids) {
        if (Strings.isNullOrEmpty(inbill.getBillCode())) {
            throw new BaseException("订单编号不存在");
        }
        if (!ObjectUtils.isEmpty(inbill.getBillVersion())) {
            EntityWrapper ew = new EntityWrapper();
            ew.eq("customer_bill_code", inbill.getBillCode());
            List<Bill> bills = baseMapper.selectListNoTenant(ew);
            if (CollectionUtils.isEmpty(bills)) {
                inbill.setBillVersion(1L);
            } else {
                if (!ObjectUtils.isEmpty(bills.get(0).getBillVersion())) {
                    inbill.setBillVersion(bills.get(0).getBillVersion() + 1);
                }
                baseMapper.deleteById(bills.get(bills.size() - 1));
            }
        }
        if (Objects.isNull(inbill.getIsAffirm())) {
            inbill.setIsAffirm(0);
        }
        inbill.setBillCode(codeUtil.getBillCode().getNextCode(null));
        new AccountBindUtil<Bill>().bindCreatorAndTenantId(inbill, true);
        inbill.setNum(ids.size());
        inbill.setGrossAmt(feeReceivableService.querySumNoTenant(ids));
        this.insert(inbill);
        List<FeeReceivable> receivables = Lists.newArrayList();
        EntityWrapper<FeePayable> feeEw = new EntityWrapper<>();
        for (Long id :
                ids) {
            FeeReceivable feeReceivable = new FeeReceivable();
            feeReceivable.setId(id);
            feeReceivable.setStatus(1);
            receivables.add(feeReceivable);
            billDetailService.insert(new BillDetail(null, inbill.getId(), id));
        }
        feeReceivableService.updateBatchById(receivables);
    }

    /**
     * 修改审核状态
     *
     * @param billCode
     * @param isAffirm
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateBillAffirmState(String billCode, Integer isAffirm) {
        try {
            //审核信息
            if (Strings.isNullOrEmpty(billCode)) {
                throw new BaseException("请传入账单编号");
            }
            if (Objects.isNull(isAffirm)) {
                throw new BaseException("请确认是否审核");
            }
            //获取对应账单进行修改
            EntityWrapper ew = new EntityWrapper();
            ew.eq("bill_code", billCode);
            ew.orderBy("bill_version", false);
            List<BillIo> billIos = billIoService.selectListNoTenant(ew);
            if (CollectionUtils.isEmpty(billIos)) {
                throw new BaseException("客户账单不存在");
            }
            BillIo billIo = billIos.get(0);
            billIo.setIsAffirm(isAffirm);
            billIoService.updateById(billIo);
            //获取对应应付账单进行修改
            EntityWrapper<Bill> ewBill = new EntityWrapper<>();
            ewBill.eq("customer_bill_id", billIo.getId());
            ewBill.eq("customer_bill_code", billIo.getBillCode());
            List<Bill> bills = baseMapper.selectListNoTenant(ewBill);
            if (CollectionUtils.isEmpty(bills)) {
                throw new BaseException("对应应收账单信息不存在");
            }
            Bill bill = bills.get(0);
            bill.setIsAffirm(isAffirm);
            baseMapper.updateById(bill);
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            throw new BaseException("绑定结果失败");
        }
    }

    /**
     * 根据应付账款生成应付账单
     *
     * @param feePayableIds
     * @param type
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<Bill> createBillByFeePayable(List<Long> feePayableIds, String type) {
        List<Bill> bills = new ArrayList<>();
        //获取传入的分组类型
        String sqlType = "";
        Integer billProperty = 0;
        if ("10".equals(type)) {
            sqlType = "payer_id";
            billProperty = 10;
        } else if ("20".equals(type)) {
            sqlType = "fleet_id";
            billProperty = 20;
        } else if ("30".equals(type)) {
            sqlType = "driver_id";
            billProperty = 30;
        } else {
            throw new BaseException("账单类型异常");
        }
        //获取type分组id
        EntityWrapper<FeePayable> feeTypeEw = new EntityWrapper<>();
        feeTypeEw.setSqlSelect(sqlType);
        feeTypeEw.in("id", feePayableIds);
        feeTypeEw.groupBy(sqlType);
        List<Object> groupByTypeId = feePayableService.selectObjs(feeTypeEw);
        JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
        String userName = null;
        if (account != null) {
            userName = account.getUsername();
        }
        //根据每组信息获取绑定，并新增账单
        for (Object typeId :
                groupByTypeId) {
            //获取每组的账款
            EntityWrapper<FeePayable> ew = new EntityWrapper<>();
            ew.eq(sqlType, typeId);
            ew.in("id", feePayableIds);
            List<FeePayable> feePayables = feePayableService.selectList(ew);
            if (!CollectionUtils.isEmpty(feePayables)) {
                //新增账单
                Bill bill = new Bill();
                bill.setIsAffirm(0);
                bill.setBillStatus("10");
                bill.setBillProperty(billProperty);
                bill.setBillProp(0);
                bill.setBillType("20");
                bill.setNum(feePayables.size());
                bill.setBillCode(codeUtil.getBillCode().getNextCode(null));
                bill.setIsDelete(0);
                bill.setPayeeId(Long.valueOf(typeId.toString()));
                if ("10".equals(type)) {
                    bill.setPayeeName(feePayables.get(0).getPayeeName());
                } else if ("20".equals(type)) {
                    bill.setPayeeName(feePayables.get(0).getFleetName());
                } else if ("30".equals(type)) {
                    bill.setPayeeName(feePayables.get(0).getDriverName());
                }
                bill.setPayerId(feePayables.get(0).getPayerId());
                bill.setPayerName(feePayables.get(0).getPayerName());
                // 创建人
                bill.setCreateUser(userName);
                new AccountBindUtil<Bill>().bindCreatorAndTenantId(bill, true);
                baseMapper.insert(bill);
//                gross_amt
                //计算总金额并绑定详明信息
                BigDecimal grossAmt = new BigDecimal(0).setScale(2);
                List<BillDetail> billDetails = new ArrayList<>();
                for (FeePayable feePayable :
                        feePayables) {
                    if (Objects.nonNull(feePayable.getActualAmt())) {
                        grossAmt = grossAmt.add(feePayable.getActualAmt());
                    }
                    billDetails.add(new BillDetail(null, bill.getId(), feePayable.getId()));
                }
                //批量新增详明并修改账单总金额
                billDetailService.insertBatch(billDetails);
                bill.setGrossAmt(grossAmt);
                baseMapper.updateById(bill);
                bills.add(bill);
            }
        }
        FeePayable feePayable = new FeePayable();
        feePayable.setStatus(1);
        EntityWrapper updateStatuEw = new EntityWrapper<>();
        updateStatuEw.in("id", feePayableIds);
        feePayableService.update(feePayable, updateStatuEw);
        return bills;
    }

    /**
     * 修改账单状态
     * 根据账单code修改对应信息的状态
     *
     * @param billCode
     * @param billStatus
     */
    @Override
    public void updateBillIo(String billCode, String billStatus) {
        Bill bill = new Bill();
        bill.setBillStatus(billStatus);
        EntityWrapper<Bill> ew = new EntityWrapper<>();
        ew.eq("customer_bill_code", billCode);
        this.update(bill, ew);
    }

    /**
     * 根据账单ID得到账单信息和应收账款信息
     * 获取账单对应账款详明
     *
     * @param id
     * @return
     */
    @Override
    public BillFeeDetailVO getBillIdToAnBilldFee(String id) {
        //验证数据
        if (!StringUtils.hasText(id)) {
            throw new BaseException("账单ID不能为空！");
        }
        EntityWrapper<Bill> billEW = new EntityWrapper();
        billEW.eq("id", id);
        List<Bill> bills = baseMapper.selectListNoTenant(billEW);
        if (CollectionUtils.isEmpty(bills)) {
            return null;
        }
        Bill bill = bills.get(0);
        BillFeeDetailVO billFeeDetailVO = getBillFeeVo(bill);
        return billFeeDetailVO;
    }

    /**
     * 根据账单ID得到账单信息和应收账款信息
     * 获取账单对应账款详明
     *
     * @param idList
     * @return
     */
    @Override
    public List<BillFeeDetailVO> getBillIdToAnBilldFeeList(List<Long> idList) {
        if (!CollectionUtils.isEmpty(idList)) {

            List<BillFeeDetailVO> voList = Lists.newArrayList();

            EntityWrapper<Bill> billEW = new EntityWrapper();
            billEW.in("id", idList);
            List<Bill> billList = baseMapper.selectListNoTenant(billEW);
            if (!CollectionUtils.isEmpty(billList)) {
                billList.forEach(bill -> {
                    BillFeeDetailVO billFeeDetailVO = getBillFeeVo(bill);
                    voList.add(billFeeDetailVO);
                });
            }
            return voList;
        }
        return null;
    }

    /**
     * 转换
     *
     * @param bill
     * @return
     */
    private BillFeeDetailVO getBillFeeVo(Bill bill) {
        BillFeeDetailVO billFeeDetailVO = new BillFeeDetailVO();
        //将账单数据合并到vo传输对象中
        BeanUtils.copyProperties(bill, billFeeDetailVO);
        //根据账单ID得到多个账单明细
        List<BillDetail> billDetailList = billDetailService.getBillDetailList(bill.getId());
        //获取账单明细绑定的对应账款id详明
        List<Long> feeIds = Lists.newArrayList();
        billDetailList.forEach(billDetail -> feeIds.add(billDetail.getFeeId()));
        //以账单类型判断帐单明细所绑定的对应账单
        if (!CollectionUtils.isEmpty(feeIds)) {
            if (BILLRECEIVABLETYPE.equals(bill.getBillType())) {
                //应收
                EntityWrapper<FeeReceivable> feeEW = new EntityWrapper();
                feeEW.in("id", feeIds);
                List<FeeReceivable> feeReceivables = feeReceivableService.getFeeReceivableList(feeEW);
                billFeeDetailVO.setFeeReceivableList(feeReceivables);
            } else if (BILLPAYABLETYPE.equals(bill.getBillType())) {
                //应付
                EntityWrapper<FeePayable> feeEW = new EntityWrapper();
                feeEW.in("id", feeIds);
                List<FeePayableVO> feePayables = feePayableService.selectPayableAndPriceDtlListNoTenant(feeEW);
                billFeeDetailVO.setFeePayablesList(feePayables);
            } else {
                throw new BaseException("该账单无类型");
            }
        }
        return billFeeDetailVO;
    }

    /**
     * 根据对应客户账单code获取对应账单信息
     *
     * @param codes
     * @return
     */
    @Override
    public List<Bill> selectBillListByCustomerBillCode(List<String> codes) {
        EntityWrapper<Bill> billEntityWrapper = new EntityWrapper<>();
        billEntityWrapper.in("customer_bill_code", codes);
        return this.selectList(billEntityWrapper);
    }

    /**
     * 批量确认账单
     *
     * @param idList
     */
    @Override
    public void batchConfirmBill(List<Long> idList) {
        LOGGER.info("BillServiceImpl.batchConfirmBill param: {}", idList);
        if (CollectionUtils.isEmpty(idList)) {
            throw new BaseException("请选择要确认的数据");
        }
        // TODO 校验暂时不要

        List<Bill> billList = Lists.newArrayList();
        idList.stream().forEach(id -> {
            Bill bill = new Bill();
            bill.setId(id);
            bill.setBillStatus("30");
            billList.add(bill);
        });
        this.updateBatchById(billList);

    }

    /**
     * 批量删除账单
     *
     * @param idList
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void reset(List<Long> idList, int resetType) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new BaseException("请选择数据!");
        }
        // 删除主表
        EntityWrapper<Bill> billEw = new EntityWrapper<>();
        billEw.in("id", idList);
        List<Bill> bills = this.selectList(billEw);
        if (!CollectionUtils.isEmpty(bills)) {
            bills.forEach(bill -> {
                if (!"10".equals(bill.getBillStatus())) {
                    throw new BaseException("只能重置未审核的账单");
                }
            });
        }
        Bill bill = new Bill();
        bill.setBillStatus("50");
        this.update(bill, billEw);

        // 更新账款为未出账
        Wrapper<BillDetail> ew = new EntityWrapper<>();
        ew.in("bill_id", idList);
        List<BillDetail> detailList = billDetailService.selectList(ew);
        if (!CollectionUtils.isEmpty(detailList)) {
            List<Long> feeIdList = Lists.newArrayList();
            detailList.stream()
                    .filter(detail -> detail.getFeeId() != null)
                    .forEach(detail -> {
                        feeIdList.add(detail.getFeeId());
                    });
            if (!CollectionUtils.isEmpty(feeIdList)) {
                // 更新应付状态账款
                EntityWrapper<FeePayable> feePayEw = new EntityWrapper<>();
                feePayEw.in("id", feeIdList);

                FeePayable updateFeePay = new FeePayable();
                updateFeePay.setStatus(0);

                feePayableService.update(updateFeePay, feePayEw);
            }
        }

        // 删除明细
        billDetailService.delete(ew);
        billEw.setSqlSelect("payee_id");
        List<Object> payeeIdsObj = selectObjs(billEw);
        List<Long> ids = new ArrayList<>();
        if (!CollectionUtils.isEmpty(payeeIdsObj)) {
            payeeIdsObj.forEach(o -> {
                if (org.apache.commons.lang3.StringUtils.isNumeric(o.toString())) {
                    ids.add(Long.parseLong(o.toString()));
                }
            });
        }
        if (0 == resetType) {
            Map<String, Object> chargeEwMapper = new HashMap<>();
            chargeEwMapper.put("fleetIds", ids);
            chargeEwMapper.put("isStart", 1);
            List<ChargeOffRule> chargeOffRules = chargeOffRuleService.selectChargeOffRuleList(chargeEwMapper);
            if (!CollectionUtils.isEmpty(chargeOffRules)) {
                chargeOffRules.forEach(chargeOffRule -> {
                    EntityWrapper<FeePayable> feePayableEntityWrapper = new EntityWrapper<>();
                    feePayableEntityWrapper.ne("source_sys", 1);
                    chargeOffRuleService.payable(chargeOffRule.getId(), null, feePayableEntityWrapper);
                });
            }
        } else if (1 == resetType) {
            EntityWrapper<FeePayable> feePayableEntityWrapper = new EntityWrapper<>();
            feePayableEntityWrapper.eq("source_sys", 1);
            feePayableEntityWrapper.in("fleet_id", ids);
            feePayableEntityWrapper.eq("load_status", 20);
            feePayableEntityWrapper.eq("status", 0);
            List<FeePayable> feePayables = feePayableService.selectListNoTenant(feePayableEntityWrapper);
            if (!CollectionUtils.isEmpty(feePayables)) {
                chargeOffRuleService.createBillAndDetailByFees(feePayables, "系统");
            }
        }
    }

    @Override
    public void updateBillAffirmDeductSum(Long id, BigDecimal deductSum) {
        Bill bill = new Bill();
        bill.setId(id);
        bill.setDeductSum(deductSum);
        this.updateById(bill);
    }

    /**
     * 锁定账单
     *
     * @param idList
     */
    @Override
    public void lockBill(List<Long> idList) {
        if (!CollectionUtils.isEmpty(idList)) {
            EntityWrapper<Bill> entityWrapper = new EntityWrapper();
            entityWrapper.in("id", idList);
            Bill bill = new Bill();
            bill.setIsLock(1);
            update(bill, entityWrapper);
        }
    }

    /**
     * 清除锁定
     *
     * @param idList
     */
    @Override
    public void cleanLockBill(List<Long> idList) {
        if (!CollectionUtils.isEmpty(idList)) {
            EntityWrapper<Bill> entityWrapper = new EntityWrapper();
            entityWrapper.in("id", idList);
            Bill bill = new Bill();
            bill.setIsLock(0);
            update(bill, entityWrapper);
        }
    }

    /**
     * 计算合同比例和金额
     *
     * @param bill
     * @return
     */
    @Override
    public BigDecimal computeContractMoney(Bill bill) {
        if (Objects.nonNull(bill) && Objects.nonNull(bill.getId())) {
            Bill defaultBill = selectById(bill.getId());
            if (Objects.isNull(defaultBill)) {
                return BigDecimal.ZERO;
            }
            // 页面传入的金额
            BigDecimal allSumMon = bill.getGrossAmt();
            if (Objects.isNull(allSumMon)) {
                return BigDecimal.ZERO;
            }
            // 获取明细
            List<BillDetail> billDetailList = billDetailService.getBillDetailList(bill.getId());
            if (CollectionUtils.isEmpty(billDetailList)) {
                return BigDecimal.ZERO;
            }
            List<Long> feeIdList = Lists.newArrayList();
            billDetailList.forEach(dtl -> {
                feeIdList.add(dtl.getFeeId());
            });
            if (CollectionUtils.isEmpty(feeIdList)) {
                return BigDecimal.ZERO;
            }
            EntityWrapper<FeePayable> feeEw = new EntityWrapper<>();
            feeEw.setSqlSelect("quote_id");
            feeEw.in("id", feeIdList);
            feeEw.isNotNull("quote_id");
            List<Object> objectList = feePayableService.selectObjs(feeEw);
            if (CollectionUtils.isEmpty(objectList)) {
                return BigDecimal.ZERO;
            }
            List<Long> quoteIdList = Lists.newArrayList();
            objectList.forEach(obj -> {
                quoteIdList.add(Long.valueOf(obj.toString()));
            });
            List<Quote> quoteList = quoteService.selectBatchIds(quoteIdList);
            if (CollectionUtils.isEmpty(quoteList)) {
                return BigDecimal.ZERO;
            }
            BigDecimal tempSum = BigDecimal.ZERO;
            Set<Long> contractIdSet = new HashSet<>();
            for (Quote quote : quoteList) {
                if (quote.getContractId() != null && !contractIdSet.contains(quote.getContractId())) {
                    Contract contract = contractService.selectById(quote.getContractId());
                    EntityWrapper<ContractFleetDtl> fleetEw = new EntityWrapper<>();
                    fleetEw.eq("head_id", quote.getContractId());
                    fleetEw.eq("fleet_id", defaultBill.getPayeeId());
                    List<ContractFleetDtl> contractFleetDtlList = contractFleetDtlService.selectList(fleetEw);
                    if (!CollectionUtils.isEmpty(contractFleetDtlList)) {

                        ContractFleetDtl contractFleetDtl = contractFleetDtlList.get(0);
                        BigDecimal oilRate = BigDecimal.ZERO;
                        if (Objects.nonNull(contractFleetDtl.getOilFinalpayRate())) {
                            oilRate = contractFleetDtl.getOilFinalpayRate();
                        }
                        if (FleetAttributeEnum.OFFICIAL_ATTRIBUTE.getCode().equals(contract.getContractType())) {
                            // 正式
                            tempSum = tempSum.add(allSumMon.multiply(oilRate));
                        } else if (FleetAttributeEnum.TEMP_ATTRIBUTE.getCode().equals(contract.getContractType())) {
                            // 临时
                            tempSum = tempSum.add(oilRate);
                        }
                        contractIdSet.add(quote.getContractId());
                    }
                }
            }
            return tempSum.setScale(2, BigDecimal.ROUND_HALF_UP);
            // List<FeePayable> feePayableList = feePayableService.selectBatchIds(feeIdList);
            // if (CollectionUtils.isEmpty(feePayableList)) {
            // 	return BigDecimal.ZERO;
            // }
            // FeePayable feePayable = feePayableList.get(0);
            // if (Objects.isNull(feePayable) || StringUtils.isEmpty(feePayable.getContractCode())) {
            // 	return BigDecimal.ZERO;
            // }
            // Contract contract = contractService.selectContractByCode(feePayable.getContractCode());
            // if (Objects.isNull(contract)) {
            // 	return BigDecimal.ZERO;
            // }
            // EntityWrapper<ContractFleetDtl> fleetEw = new EntityWrapper<>();
            // fleetEw.eq("head_id", contract.getId());
            // fleetEw.eq("fleet_id", defaultBill.getPayeeId());
            // List<ContractFleetDtl> contractFleetDtlList = contractFleetDtlService.selectList(fleetEw);
            // if (CollectionUtils.isEmpty(contractFleetDtlList)) {
            // 	return BigDecimal.ZERO;
            // }
            // // allSumMon
            // ContractFleetDtl contractFleetDtl = contractFleetDtlList.get(0);
            // BigDecimal oilRate = BigDecimal.ZERO;
            // if (Objects.nonNull(contractFleetDtl.getOilFinalpayRate())) {
            // 	oilRate = contractFleetDtl.getOilFinalpayRate();
            // }
            // if (FleetAttributeEnum.OFFICIAL_ATTRIBUTE.getCode().equals(contract.getContractType())) {
            // 	// 正式
            // 	return allSumMon.multiply(oilRate);
            // } else if (FleetAttributeEnum.TEMP_ATTRIBUTE.getCode().equals(contract.getContractType())) {
            // 	// 临时
            // 	return oilRate;
            // }
        }
        return BigDecimal.ZERO;
    }

    /**
     * 撤销删除账单
     *
     * @param billList
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void callBackDelBill(List<Bill> billList) {
        if (CollectionUtils.isEmpty(billList)) {
            throw new BaseException("请选择数据");
        }
        for (Bill bill : billList) {
            if (Objects.isNull(bill.getId())) {
                throw new BaseException("无关键数据匹配账单");
            }
            EntityWrapper<PayApplyDtlBill> ew = new EntityWrapper<>();
            ew.eq("bil_id", bill.getId());
            int payApplyCount = payApplyDtlBillService.selectCount(ew);
            if (payApplyCount > 0) {
                throw new BaseException(bill.getBillCode() + "已经生成支付申请, 不可撤销删除!");
            }
            // 删除账单主表
            this.deleteById(bill.getId());
            // 删除账单明细
            EntityWrapper<BillDetail> billDtlEw = new EntityWrapper<>();
            billDtlEw.eq("bill_id", bill.getId());
            List<BillDetail> billDetailList = billDetailService.selectList(billDtlEw);
            if (!CollectionUtils.isEmpty(billDetailList)) {
                List<Long> feeIdList = Lists.newArrayList();
                billDetailList.forEach(billDtl -> {
                    feeIdList.add(billDtl.getFeeId());
                });
                // 还原账款状态
                if (!CollectionUtils.isEmpty(feeIdList)) {
                    EntityWrapper<FeePayable> feePaybleEw = new EntityWrapper<>();
                    feePaybleEw.in("id", feeIdList);
                    FeePayable updateFeePayble = new FeePayable();
                    updateFeePayble.setStatus(0);
                    updateFeePayble.setGmtModify(new Date());
                    feePayableService.update(updateFeePayble, feePaybleEw);
                }
            }
            // 删除账单明细
            billDetailService.delete(billDtlEw);
        }
    }

    /**
     * 获取账单下的所有对应的运单号
     *
     * @param billIdList
     * @return
     */
    @Override
    public List<String> getBillSysWaybillId(List<Long> billIdList) {
        if (CollectionUtils.isEmpty(billIdList)) {
            return null;
        }
        List<BillDetail> billDetailList = billDetailService.getBillDetailList(billIdList);
        if (CollectionUtils.isEmpty(billDetailList)) {
            return null;
        }
        List<Long> feeIdList = Lists.newArrayList();
        billDetailList.forEach(billDetail -> {
            feeIdList.add(billDetail.getFeeId());
        });
        EntityWrapper<FeePayable> ew = new EntityWrapper<>();
        ew.setSqlSelect("distinct waybill_dtl_id");
        ew.in("id", feeIdList);
        List<Object> objectList = feePayableService.selectObjs(ew);
        if (CollectionUtils.isEmpty(objectList)) {
            return null;
        }
        List<String> waybillIdList = Lists.newArrayList();
        objectList.forEach(obj -> {
            waybillIdList.add(obj.toString());
        });
        return waybillIdList;
    }
}
